package interview.algorithms.tree;

import common.TreeNode;

import java.util.ArrayList;
import java.util.LinkedList;

/**
 * 二叉树
 * @author fance
 * @date 2018/5/15 16:04
 */
public class Solution {

    public ArrayList<Integer> preOrderUnRecur(TreeNode root) {
        ArrayList<Integer> res = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList<>();
        if (root == null) {
            return res;
        }
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            res.add(cur.val);
            if (cur.right != null) {
                stack.push(cur.right);
            }
            if (cur.left != null) {
                stack.push(cur.left);
            }
        }
        return res;
    }



    public ArrayList<Integer> inOrderUnRecur(TreeNode root) {
        ArrayList<Integer> res = new ArrayList<>();
        if (root != null) {
            LinkedList<TreeNode> stack = new LinkedList<>();
            while (!stack.isEmpty() || root != null) {
                if (root != null) {
                    stack.push(root);
                    root = root.left;
                } else {
                    TreeNode cur = stack.pop();
                    res.add(cur.val);
                    root = cur.right;
                }
            }
        }
        return res;
    }




    public ArrayList<Integer> postOrderUnRecur(TreeNode root) {
        ArrayList<Integer> res = new ArrayList<>();

        if (root != null) {
            LinkedList<TreeNode> stack1 = new LinkedList<>();
            LinkedList<TreeNode> stack2 = new LinkedList<>();
            stack1.push(root);
            while (!stack1.isEmpty()) {
                root = stack1.pop();
                stack2.push(root);
                if (root.left != null) {
                    stack1.push(root.left);
                }
                if (root.right != null) {
                    stack1.push(root.right);
                }
            }
            while (!stack2.isEmpty()) {
                res.add(stack2.pop().val);
            }
        }
        return res;
    }

    // 层序遍历二叉树  利用队列记录每一层节点个数
    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if (pRoot == null) {
            return res;
        }
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(pRoot);
        while (!queue.isEmpty()) {
            int curNum = queue.size();
            ArrayList<Integer> tmp = new ArrayList<>();
            for (int i = 0; i < curNum; i++) {
                TreeNode cur = queue.poll();
                tmp.add(cur.val);
                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            res.add(tmp);
        }
        return res;
    }

    /**
     *  106. 从中序与后序遍历序列构造二叉树
     * @param inorder
     * @param postorder
     * @return
     */
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if (postorder == null || postorder.length < 1) {
            return null;
        }
        return buildTreeCore(inorder,0,inorder.length - 1,postorder,0,postorder.length - 1);
    }
    private TreeNode buildTreeCore(int[] inorder,int inSt,int inEnd,
                                   int[] postorder,int postSt,int postEnd) {
        if (postSt > postEnd || inSt > inEnd || postEnd < 0 || inEnd >= inorder.length) {
            return null;
        }
        int rootVal = postorder[postEnd];
        int rootIndexInOrder = 0;
        for (int i = inSt; i <= inEnd; i++) {
            if (inorder[i] == rootVal) {
                rootIndexInOrder = i;
            }
        }
        int offset = rootIndexInOrder - inSt;
        TreeNode root = new TreeNode(rootVal);
        root.left = buildTreeCore(inorder,inSt,rootIndexInOrder - 1,postorder,postSt,postSt + offset - 1);
        root.right = buildTreeCore(inorder,rootIndexInOrder + 1,inEnd,postorder, postSt + offset,postEnd - 1);
        return root;
    }

}
